/*
 * @Author      : ZhouQiJun
 * @Date        : 2025-08-11 03:58:37
 * @LastEditors : ZhouQiJun
 * @LastEditTime: 2025-08-11 04:13:59
 * @Description : 分辨率计算器
 */
import type { ProjCode } from '@ol/types'
import { isNil } from 'es-toolkit'

import { getWidth } from 'ol/extent'
import { get } from 'ol/proj'

// 使用 Map 缓存 初始分辨率 避免重复计算
const cache = new Map<string, number>()

function calcR0(projCode: ProjCode = 'EPSG:3857', tileWidth = 256): number | undefined {
  const key = `${projCode}-${tileWidth}`
  if (cache.has(key)) {
    return cache.get(key)!
  }
  const projection = get(projCode)
  if (isNil(projection)) return undefined
  const extent = projection.getExtent()
  const extentWidth = getWidth(extent)
  const r0 = extentWidth / tileWidth
  cache.set(key, r0)
  return r0
}
/**
 * 根据层级计算分辨率
 * @param zoom 地图层级
 * @param projCode EPSG 投影 默认 EPSG:3857
 * @param tileWidth 瓦片大小 默认 256
 * @returns 分辨率
 */
export function calcResolution(zoom: number, projCode: ProjCode = 'EPSG:3857', tileWidth = 256) {
  const r0 = calcR0(projCode, tileWidth)
  if (isNil(r0)) return undefined
  return r0 / Math.pow(2, zoom)
}

/**
 * 根据分辨率计算层级
 * @param resolution 分辨率
 * @param projCode EPSG 投影 默认 EPSG:3857
 * @param tileWidth 瓦片大小 默认 256
 * @returns zoom
 */
export function calcZoom(resolution: number, projCode: ProjCode = 'EPSG:3857', tileWidth = 256) {
  const r0 = calcR0(projCode, tileWidth)
  if (isNil(r0)) return undefined
  return Math.log2(r0 / resolution)
}
